//
//  BaseViewController.m
//  CCFoundation
//
//  Created by CC on 2018/5/26.
//  Copyright © 2018年 CC. All rights reserved.
//

#import "BaseViewController.h"
#import "LcFoundation.h"
#import "NavigationTitleView.h"

@interface BaseViewController () <UINavigationControllerDelegate, UIImagePickerControllerDelegate>

@property(nonatomic, strong) NSMutableArray* cellAdapters;
@property(nonatomic, strong) NSMutableArray* weakTableViews;
@property(nonatomic, assign) NSInteger presentDelayTimes;
@property(nonatomic, assign) BOOL listeningAppState;

@property(nonatomic, assign) BOOL presenting;

@property(nonatomic, assign) BOOL interactivePopDisabled;

@end

@implementation BaseViewController

- (instancetype)init {
  self = [super init];
  return self;
}

- (instancetype)initWithNibName:(NSString*)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil {
  if (nibNameOrNil == nil) {
    nibNameOrNil = NSStringFromClass([self class]);
  }
  if ([[NSBundle mainBundle] pathForResource:nibNameOrNil ofType:@"nib"] == nil) {
    nibNameOrNil = nil;
  }
  self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
  return self;
}

#pragma mark - View Life Cycle
- (void)viewDidLoad {
  [super viewDidLoad];
  [[LcNotificationCenter sharedInstance] registerDelegate:self];
  [self fixLayoutWithSafeArea];
  UIViewController* parentViewController = self.parentViewController;
  if (parentViewController != nil) {
    if (parentViewController != self.navigationController &&
        parentViewController != self.tabBarController) {
      [self hideTopGuideBackgroundView];
    }
  }
  UITapGestureRecognizer* tap =
      [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
  self->_viewTapGesture = tap;
  tap.cancelsTouchesInView = NO;
  [self.view addGestureRecognizer:tap];

  self.navigationController.interactivePopGestureRecognizer.enabled = NO;

#if DEBUG
  [[UIApplication sharedApplication] setApplicationSupportsShakeToEdit:YES];
#endif
}

- (void)viewWillAppear:(BOOL)animated {
  [super viewWillAppear:animated];
  self->_viewState = ControllerViewStateAppearing;
  [UIApplication sharedApplication].statusBarStyle = self.preferredStatusBarStyle;
  if (self.needRefreshWhenAppear) {
    self.needRefreshWhenAppear = NO;
    [self refreshWhenAppear];
  }
  if (self.weakTableViews.count > 0) {
    for (int i = ((int)self.weakTableViews.count) - 1; i >= 0; --i) {
      LcWeakReference* weakTableView = self.weakTableViews[i];
      UITableView* tableView = weakTableView.object;
      if (tableView == nil) {
        [self.weakTableViews removeObjectAtIndex:i];
      } else {
        [tableView deselectRow];
      }
    }
  }
}

- (void)viewDidAppear:(BOOL)animated {
  // LcLog(@"%@ viewDidAppear:", self.class);
  [super viewDidAppear:animated];
  self->_viewState = ControllerViewStateAppeared;
  [self addListenApplicationState];
  if (self.loadingIndicatorShowing) {
    [self showLoadingIndicator];
  } else {
    [self hideLoadingIndicator];
  }
}

- (void)viewWillDisappear:(BOOL)animated {
  [super viewWillDisappear:animated];
  self->_viewState = ControllerViewStateDisappearing;
}

- (void)viewDidDisappear:(BOOL)animated {
  [super viewDidDisappear:animated];
  self->_viewState = ControllerViewStateDisappeared;
}

- (BOOL)viewAppeared {
  return self.viewState == ControllerViewStateAppeared;
}

- (BOOL)viewDisappeared {
  return self.viewState == ControllerViewStateDisappeared;
}

- (BOOL)isControllerAnimating {
  return self.viewState == ControllerViewStateDisappearing ||
         self.viewState == ControllerViewStateAppearing;
}

- (BOOL)hidesBottomBarWhenPushed {
  UIViewController* rootViewController = self.navigationController.rootViewController;
  if (rootViewController == nil || rootViewController == self) {
    return NO;
  }
  return YES;
}

- (void)dismissToFromViewWithCompletion:(void (^)(void))completion {
  self->_dismissed = YES;
  [self.view endEditing:YES];
  if (self.fromViewController == nil) {
    [self dismissViewControllerAnimated:YES completion:nil];
  } else {
    [self.fromViewController dismissViewControllerAnimated:YES completion:nil];
  }
}

- (void)popToFromViewController {
  self->_dismissed = YES;
  [self.view endEditing:YES];
  if (self.fromViewController == nil) {
    [self.navigationController popToRootViewControllerAnimated:YES];
  } else {
    [self.navigationController popToViewController:self.fromViewController animated:YES];
  }
}

- (void)refreshWhenAppear {
}

- (void)showLoadingIndicator {
  LC_CHECK_IS_MAIN_THREAD();
  self.loadingIndicatorShowing = YES;
  if (self.viewAppeared) {
    [LcLoadingIndicatorView showNormal:YES];
  }
}

- (void)hideLoadingIndicator {
  LC_CHECK_IS_MAIN_THREAD();
  [LcLoadingIndicatorView hideNormal];
  self.loadingIndicatorShowing = NO;
}

- (BOOL)needAutomaticallyAdjustsScrollViewInsets {
  return NO;
}

// MARK: - SafeAreaInsets
- (void)viewSafeAreaInsetsDidChange {
  [super viewSafeAreaInsetsDidChange];
  [self adjustTopGuideHeight];
}

- (void)adjustTopGuideHeight {
  self.topGuideHeightConstraint.constant = [self calculateTopGuideHeight];
}

- (void)hideTopGuideBackgroundView {
  self.topGuideBackgroundView.hidden = YES;
  self.topGuideHeightConstraint.constant = 0;
}

- (UIEdgeInsets)sv_safeAreaInsets {
  return self.view.safeAreaInsets;
}

- (CGFloat)calculateTopGuideHeight {
  UIEdgeInsets safeAreaInsets = self.sv_safeAreaInsets;
  if (self.navigationController == nil || self.navigationController.navigationBarHidden) {
    return safeAreaInsets.top + 44;
  }
  return safeAreaInsets.top;
}

- (void)fixLayoutWithSafeArea {
  if (self.topGuideBackgroundView != nil) {
    [self setWhiteNavigationBar];
    [self showDarkBackButton];
    self.topGuideBackgroundView.clipsToBounds = NO;
    for (NSLayoutConstraint* layoutConstraint in self.topGuideBackgroundView.constraints) {
      if (layoutConstraint.firstAttribute == NSLayoutAttributeHeight) {
        self.topGuideHeightConstraint = layoutConstraint;
        break;
      }
    }
    [self.view bringSubviewToFront:self.topGuideBackgroundView];

    if (!self.hideTitleSeparatorLine) {
      UIImageView* seperateLineView = [self.topGuideBackgroundView viewWithTag:1011];
      if (seperateLineView == nil) {
        seperateLineView = [[UIImageView alloc]
            initWithFrame:CGRectMake(0, LcUIUtility.topGuideY, [LcUIUtility screenWidth], 2)];
        seperateLineView.image = [UIImage imageNamed:@"navigation_shadow"];
        seperateLineView.tag = 1011;
        [self.topGuideBackgroundView addSubview:seperateLineView];
      } else {
        seperateLineView.frame = CGRectMake(0, LcUIUtility.topGuideY, [LcUIUtility screenWidth], 2);
      }
    }
  }
}

- (void)setWhiteNavigationBar {
  self.topGuideBackgroundView.backgroundColor = LC_COLOR_WHITE;
}

- (void)setTransparentNavigationBar {
  self.topGuideBackgroundView.backgroundColor = UIColor.clearColor;
}

- (BOOL)hideTitleSeparatorLine {
  return YES;
}

#pragma mark - NavigaitonItem

- (void)navigationBack {
  // self.navigationController can be null even if these is a navigation
  // controller, perhaps a system bug
  if (self.navigationController != nil) {
    self->_dismissed = YES;
    [self.navigationController popViewControllerAnimated:YES];
  }
}

- (void)cancel {
  [self cancelWithAnimated:YES];
}

- (void)cancelWithAnimated:(BOOL)animated {
  [self cancelWithAnimated:animated completion:nil];
}

- (void)cancelOrNavigationBack {
  if (self.presentingViewController != nil) {
    [self cancel];
  } else {
    [self navigationBack];
  }
}

- (void)cancelWithAnimated:(BOOL)animated completion:(void (^)(void))completion {
  self->_dismissed = YES;
  [self.view endEditing:YES];
  if (self.presentingViewController != nil) {
    UIStatusBarStyle statusBarStyle = UIStatusBarStyleLightContent;
    if ([self.presentingViewController isKindOfClass:[UINavigationController class]]) {
      statusBarStyle = [[[(UINavigationController*)self.presentingViewController viewControllers]
          lastObject] preferredStatusBarStyle];
    } else {
      statusBarStyle = self.presentingViewController.preferredStatusBarStyle;
    }
    [UIApplication sharedApplication].statusBarStyle = statusBarStyle;
  }
  [self dismissViewControllerAnimated:animated completion:completion];
}

- (void)setButtonRightMargin:(UIButton*)button {
  // fix for navigation bar right margin
  if (@available(iOS 13.0, *)) {
  } else {
    if (@available(iOS 11, *)) {
      button.contentEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 15);
    } else {
      button.contentEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 7);
    }
  }
}

- (CGFloat)defaultItemMargin {
  if (@available(iOS 13.0, *)) {
    return 0;
  } else {
    if ([LcUIUtility screenWidth] >= 414) {
      // only iPhone6+ in non-zoomed mode
      return -12;
    } else {
      return -8;
    }
  }
}

- (UIBarButtonItem*)whiteBarButtonItemWithTitle:(NSString*)title
                                         target:(id)target
                                         action:(SEL)action {
  LC_CHECK_NOT_EMPTY(title);
  LC_CHECK_NOT_NULL(target);
  UIButton* button =
      [UIButton commonWhiteNavigationButtonWithTitle:title target:target action:action];
  [self setButtonRightMargin:button];
  UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
  return barButtonItem;
}

- (UIBarButtonItem*)darkBarButtonItemWithTitle:(NSString*)title
                                        target:(id)target
                                        action:(SEL)action {
  LC_CHECK_NOT_EMPTY(title);
  LC_CHECK_NOT_NULL(target);
  UIButton* button =
      [UIButton commonDarkNavigationButtonWithTitle:title target:target action:action];
  [self setButtonRightMargin:button];
  UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
  return barButtonItem;
}

- (UIBarButtonItem*)darkBackButtonItem {
  UIButton* button = [UIButton customButtonWithImageName:@"navbar_back" target:self action:@selector(navigationBack)];
  UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
  return barButtonItem;
}

- (UIBarButtonItem*)darkBackButtonItemWithTarget:(id)target action:(SEL)action {
  UIButton* button = [UIButton commonDarkBackButtonWithTitle:@" " target:target action:action];
  button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
  UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
  return barButtonItem;
}

- (UIBarButtonItem*)whiteBackButtonItem {
  UIButton* button =
      [UIButton commonWhiteBackButtonWithTitle:@" " target:self action:@selector(navigationBack)];
  button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
  UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
  return barButtonItem;
}

- (UIBarButtonItem*)whiteBackButtonItemWithTarget:(id)target action:(SEL)action {
  UIButton* button = [UIButton commonWhiteBackButtonWithTitle:@" " target:target action:action];
  button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
  UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
  return barButtonItem;
}

- (UIBarButtonItem*)grayButtonItemWithButton:(UIButton*)button {
  return [self buttonItemWithButton:button fontColor:LC_COLOR_GRAY];
}

- (UIBarButtonItem*)buttonItemWithButton:(UIButton*)button fontColor:(UIColor*)fontColor {
  return [self buttonItemWithButton:button fontColor:LC_COLOR_GRAY highlightedColor:LC_COLOR_GRAY];
}

- (UIBarButtonItem*)buttonItemWithButton:(UIButton*)button
                               fontColor:(UIColor*)fontColor
                        highlightedColor:(UIColor*)highlightedColor {
  [button setTitleColor:fontColor forState:UIControlStateNormal];
  [button setTitleColor:highlightedColor forState:UIControlStateHighlighted];
  UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
  return barButtonItem;
}

- (UIBarButtonItem*)cancelButtonItem {
  return [self cancelButtonItem:LC_COLOR_WHITE_80 highlightedColor:LC_COLOR_WHITE_60];
}

- (UIBarButtonItem*)cancelButtonItem:(UIColor*)fontColor
                    highlightedColor:(UIColor*)highlightedColor {
  UIButton* button =
      [UIButton commonWhiteNavigationButtonWithTitle:@"取消" target:self
                                              action:@selector(cancel)];
  [button setLcFont:[LcFont w80m17]];
  return [self buttonItemWithButton:button fontColor:fontColor highlightedColor:highlightedColor];
}

- (UIBarButtonItem*)closeButtonItem {
  UIButton* button = [UIButton customButtonWithImageName:@"navbar_close" target:self action:@selector(cancel)];
  UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
  return barButtonItem;
}

- (UIBarButtonItem*)darkCloseButtonItem {
  UIButton* button =
      [UIButton commonWhiteNavigationButtonWithTitle:@"关闭" target:self
                                              action:@selector(cancel)];
  [button setLcFont:[LcFont dm17]];
  [button setTitleColor:LC_COLOR_WHITE_60 forState:UIControlStateHighlighted];
  UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
  return barButtonItem;
}

- (UIBarButtonItem*)closeButtonItemWithTarget:(id)target action:(SEL)action {
  LC_CHECK_NOT_NULL(target);
  UIButton* button = [UIButton closeButtonWithTarget:target action:action];
  UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
  return barButtonItem;
}

- (UIBarButtonItem*)whiteCloseButtonItemWithTarget:(id)target action:(SEL)action {
  LC_CHECK_NOT_NULL(target);
  UIButton* button = [UIButton whiteCloseButtonWithTarget:target action:action];
  UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
  return barButtonItem;
}

- (UIBarButtonItem*)refreshButtonItemWithTarget:(id)target action:(SEL)action {
  LC_CHECK_NOT_NULL(target);
  UIButton* button = [UIButton refreshButtonWithTarget:target action:action];
  UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
  return barButtonItem;
}

- (UIBarButtonItem*)searchButtonItemWithTarget:(id)target action:(SEL)action {
  LC_CHECK_NOT_NULL(target);
  UIButton* button = [UIButton searchButtonWithTarget:target action:action];
  UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
  return barButtonItem;
}

- (UIBarButtonItem*)customButtonItemWithImageName:(NSString*)imageName
                                           target:(id)target
                                           action:(SEL)action {
  LC_CHECK_NOT_NULL(target);
  UIButton* button = [UIButton customButtonWithImageName:imageName target:self action:action];
  button.frame = CGRectMake(0, 0, 30, 30);
  UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
  return barButtonItem;
}

- (UIBarButtonItem*)customButtonItemWithImageName:(NSString*)imageName
                                           target:(id)target
                                           action:(SEL)action
                                            style:(UIControlContentHorizontalAlignment)style {
  LC_CHECK_NOT_NULL(target);
  UIButton* button = [UIButton customButtonWithImageName:imageName target:self action:action];
  button.contentHorizontalAlignment = style;
  UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
  return barButtonItem;
}

- (UIBarButtonItem*)moreButtonItemWithTarget:(id)target action:(SEL)action {
  LC_CHECK_NOT_NULL(target);
  UIButton* button = [UIButton moreButtonWithTarget:target action:action];
  UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
  return barButtonItem;
}

- (UIBarButtonItem*)shareButtonItemWithTarget:(id)target action:(SEL)action {
  LC_CHECK_NOT_NULL(target);
  UIButton* button = [UIButton shareButtonWithTarget:target action:action];
  UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
  return barButtonItem;
}

- (void)showDarkBackButton {
  UIBarButtonItem* negativeSeperator =
      [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
                                                    target:nil
                                                    action:nil];
  negativeSeperator.width = self.defaultItemMargin;
  self.navigationItem.leftBarButtonItems = @[
    self.darkBackButtonItem,
  ];
}

- (void)showDarkBackButtonWithTarget:(id)target action:(SEL)action {
  UIBarButtonItem* item = [self darkBackButtonItemWithTarget:target action:action];
  self.navigationItem.leftBarButtonItems = @[ item ];
}

- (void)showWhiteBackButton {
  [self showWhiteBackArrowButton];
}

- (void)showWhiteBackButtonWithTarget:(id)target action:(SEL)action {
  UIBarButtonItem* item = [self whiteBackButtonItemWithTarget:target action:action];
  self.navigationItem.leftBarButtonItems = @[ item ];
}

- (void)showWhiteBackArrowButton {
  self.navigationItem.leftBarButtonItems = @[
    self.whiteBackButtonItem,
  ];
}

- (void)showTransparentLeftButton {
  UIButton* button = [UIButton commonWhiteBackButtonWithTitle:@" " target:self action:nil];
  button.backgroundColor = [UIColor clearColor];
  [button setImage:nil forAllState:YES];
  button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
  UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
  self.navigationItem.leftBarButtonItems = @[ barButtonItem ];
}

- (void)showTransparentRightButton {
  UIButton* button = [UIButton rightNavigationButtonWithTarget:self action:nil imageName:nil];
  button.backgroundColor = [UIColor clearColor];
  [button setImage:nil forAllState:YES];
  UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
  [self setRightItem:barButtonItem];
}

- (void)showTransparentBackButton {
  UIButton* button = [UIButton commonWhiteBackButtonWithTitle:@" " target:self action:@selector(navigationBack)];
  button.backgroundColor = [UIColor clearColor];
  [button setImage:nil forAllState:YES];
  button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
  UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
  self.navigationItem.leftBarButtonItems = @[ barButtonItem ];
}


- (void)showCancelButton {
  UIBarButtonItem* negativeSeperator =
      [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
                                                    target:nil
                                                    action:nil];
  negativeSeperator.width = self.defaultItemMargin;
  self.navigationItem.leftBarButtonItems = @[
    negativeSeperator,
    self.cancelButtonItem,
  ];
}

- (void)showBlueCancelButton {
  UIBarButtonItem* negativeSeperator =
      [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
                                                    target:nil
                                                    action:nil];
  negativeSeperator.width = self.defaultItemMargin;
  UIBarButtonItem* cancelButtonItem =
      [self cancelButtonItem:LC_COLOR_BLUE highlightedColor:LC_COLOR_BLUE_ACTIVE];
  self.navigationItem.leftBarButtonItems = @[
    negativeSeperator,
    cancelButtonItem,
  ];
}

- (void)showGrayCancelButton {
  UIBarButtonItem* negativeSeperator =
      [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
                                                    target:nil
                                                    action:nil];
  negativeSeperator.width = self.defaultItemMargin;
  UIBarButtonItem* cancelButtonItem =
      [self cancelButtonItem:LC_COLOR_GRAY highlightedColor:LC_COLOR_GRAY];
  self.navigationItem.leftBarButtonItems = @[
    negativeSeperator,
    cancelButtonItem,
  ];
}

- (void)showCloseButton {
  UIBarButtonItem* negativeSeperator =
      [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
                                                    target:nil
                                                    action:nil];
  negativeSeperator.width = self.defaultItemMargin;
  self.navigationItem.leftBarButtonItems = @[
    self.closeButtonItem,
    negativeSeperator
  ];
}

- (void)showDarkCloseButton {
  UIBarButtonItem* negativeSeperator =
      [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
                                                    target:nil
                                                    action:nil];
  negativeSeperator.width = self.defaultItemMargin;
  self.navigationItem.leftBarButtonItems = @[
    negativeSeperator,
    self.darkCloseButtonItem,
  ];
}

- (void)showGrayCloseIconButton {
  [self showGrayCloseIconButton:NAVIGATION_ALIGNMENT_LEFT imageName:@"legend_close"];
}

- (void)showGrayCloseIconButton:(NavigationAlignment)alignment imageName:(NSString*)imageName {
  if (alignment == NAVIGATION_ALIGNMENT_RIGHT) {
    UIButton* rightButton = [UIButton rightNavigationButtonWithTarget:self
                                                               action:@selector(cancel)
                                                            imageName:imageName];
    [self setRightItem:[[UIBarButtonItem alloc] initWithCustomView:rightButton]];
  } else {
    [self setLeftItem:[self customButtonItemWithImageName:imageName
                                                   target:self
                                                   action:@selector(cancel)]];
  }
}

- (void)setLeftItem:(UIBarButtonItem*)item {
  if (item == nil) {
    self.navigationItem.leftBarButtonItems = nil;
    self.navigationItem.hidesBackButton = YES;
  } else {
    [self setLeftItem:item marginOffset:0];
  }
}

- (void)setLeftItem:(UIBarButtonItem*)item marginOffset:(CGFloat)marginOffset {
  LC_CHECK_NOT_NULL(item);
  UIBarButtonItem* negativeSeperator =
      [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
                                                    target:nil
                                                    action:nil];
  negativeSeperator.width = self.defaultItemMargin + marginOffset;
  self.navigationItem.leftBarButtonItems = @[
    negativeSeperator,
    item,
  ];
}

- (void)setRightItem:(UIBarButtonItem*)item {
  if (item == nil) {
    self.navigationItem.rightBarButtonItems = nil;
  } else {
    [self setRightItem:item marginOffset:0];
  }
}

- (void)setRightItem:(UIBarButtonItem*)item marginOffset:(CGFloat)marginOffset {
  LC_CHECK_NOT_NULL(item);
  UIBarButtonItem* negativeSeperator =
      [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
                                                    target:nil
                                                    action:nil];
  negativeSeperator.width = self.defaultItemMargin + marginOffset;
  self.navigationItem.rightBarButtonItems = @[
    negativeSeperator,
    item,
  ];
}

- (void)setRightItems:(NSArray*)barButtonItems {
  LC_CHECK_NOT_EMPTY(barButtonItems);
  LC_CHECK_ELEMENT_TYPE(barButtonItems, UIBarButtonItem.class, NO);
  UIBarButtonItem* negativeSeperator =
      [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
                                                    target:nil
                                                    action:nil];
  negativeSeperator.width = self.defaultItemMargin;
  NSMutableArray* rightBarButtonItems = [NSMutableArray array];
  [rightBarButtonItems addObject:negativeSeperator];
  [rightBarButtonItems addObjectsFromArray:barButtonItems];
  self.navigationItem.rightBarButtonItems = rightBarButtonItems;
}

#pragma mark -

- (void)disableInteractivePop:(BOOL)disabled {
  self.interactivePopDisabled = disabled;
  self.navigationController.interactivePopGestureRecognizer.enabled = !self.interactivePopDisabled;
}

#pragma mark - NavigaitonTitle
- (void)setDarkSingleLineTitle:(NSString*)title {
  //  LC_CHECK_NOT_EMPTY(title);
  [self setTitle:title withLcFont:[LcFont db17]];
}
- (void)setWhiteSingleLineTitle:(NSString*)title {
  //  LC_CHECK_NOT_EMPTY(title);
  [self setTitle:title withLcFont:[LcFont wb17]];
}

- (void)setTitle:(NSString*)title withLcFont:(LcFont*)lcFont {
  //  LC_CHECK_NOT_EMPTY(title);
  LC_CHECK_NOT_NULL(lcFont);
  UIView* titleView = self.navigationItem.titleView;
  if (![titleView isKindOfClass:NavigationTitleView.class]) {
    titleView = [NavigationTitleView navigationTitleViewWithTitle:title lcFont:lcFont];
    self.navigationItem.titleView = titleView;
  } else {
    NavigationTitleView* navigationTitleView = (NavigationTitleView*)titleView;
    [navigationTitleView setTitle:title lcFont:lcFont];
    [navigationTitleView hiddenSubTitle:YES];
  }
}

- (void)setAttributedContentTitle:(NSAttributedString*)title {
  LC_CHECK_NOT_NULL(title);
  UIView* titleView = self.navigationItem.titleView;
  if (![titleView isKindOfClass:NavigationTitleView.class]) {
    titleView = [NavigationTitleView navigationTitleViewWithAttributedTitle:title];
    self.navigationItem.titleView = titleView;
  } else {
    NavigationTitleView* navigationTitleView = (NavigationTitleView*)titleView;
    [navigationTitleView setAttributedTitleTitle:title];
    [navigationTitleView hiddenSubTitle:YES];
  }
}

- (void)setTitle:(NSString*)title subTitle:(NSAttributedString*)subtitle {
  LC_CHECK_NOT_EMPTY(title);
  LC_CHECK_NOT_EMPTY(subtitle);
  UIView* titleView = self.navigationItem.titleView;
  if (![titleView isKindOfClass:NavigationTitleView.class]) {
    titleView =
        [NavigationTitleView navigationTitleViewWithLightContentTitle:title subtitle:subtitle];
    self.navigationItem.titleView = titleView;
  } else {
    NavigationTitleView* navigationTitleView = (NavigationTitleView*)titleView;
    [navigationTitleView setTitle:title titleFont:[LcFont wb17] subtitle:subtitle];
    [navigationTitleView hiddenSubTitle:NO];
  }
}

- (void)setLightContentTitle:(NSString*)title subTitle:(NSAttributedString*)subtitle {
  LC_CHECK_NOT_EMPTY(title);
  LC_CHECK_NOT_EMPTY(subtitle);
  UIView* titleView = self.navigationItem.titleView;
  if (![titleView isKindOfClass:NavigationTitleView.class]) {
    titleView =
        [NavigationTitleView navigationTitleViewWithLightContentTitle:title subtitle:subtitle];
    self.navigationItem.titleView = titleView;
  } else {
    NavigationTitleView* navigationTitleView = (NavigationTitleView*)titleView;
    [navigationTitleView setTitle:title titleFont:[LcFont wb17] subtitle:subtitle];
    [navigationTitleView hiddenSubTitle:NO];
  }
}

- (void)setDarkTitle:(NSString*)title subTitle:(NSAttributedString*)subtitle {
  LC_CHECK_NOT_EMPTY(title);
  LC_CHECK_NOT_EMPTY(subtitle);
  UIView* titleView = self.navigationItem.titleView;
  if (![titleView isKindOfClass:NavigationTitleView.class]) {
    titleView = [NavigationTitleView navigationTitleViewWithTitle:title subtitle:subtitle];
    self.navigationItem.titleView = titleView;
  } else {
    NavigationTitleView* navigationTitleView = (NavigationTitleView*)titleView;
    [navigationTitleView setTitle:title titleFont:[LcFont db17] subtitle:subtitle];
    [navigationTitleView hiddenSubTitle:NO];
  }
}

- (void)setLightAttributedContentTitle:(NSAttributedString*)title
                              subTitle:(NSAttributedString*)subtitle {
  LC_CHECK_NOT_EMPTY(title);
  LC_CHECK_NOT_EMPTY(subtitle);
  UIView* titleView = self.navigationItem.titleView;
  if (![titleView isKindOfClass:NavigationTitleView.class]) {
    titleView = [NavigationTitleView navigationTitleViewWithLightAttributedContentTitle:title
                                                                               subtitle:subtitle];
    self.navigationItem.titleView = titleView;
  } else {
    NavigationTitleView* navigationTitleView = (NavigationTitleView*)titleView;
    navigationTitleView.titleLabel.attributedText = title;
    navigationTitleView.subtitleLabel.attributedText = subtitle;
    [navigationTitleView hiddenSubTitle:NO];
  }
}

#pragma mark - CellAdapter
- (void)setCellAdapter:(LcCellAdapter*)cellAdapter forTableView:(UITableView*)tableView {
  LC_CHECK_NOT_NULL(cellAdapter);
  LC_CHECK_NOT_NULL(tableView);
  if (self.cellAdapters == nil) {
    self.cellAdapters = [NSMutableArray array];
  }
  if (self.weakTableViews == nil) {
    self.weakTableViews = [NSMutableArray array];
  }
  LC_CHECK_TRUE(self.cellAdapters.count == self.weakTableViews.count);
  tableView.dataSource = cellAdapter;
  tableView.delegate = self;
  cellAdapter.delegate = self;
  cellAdapter.tableView = tableView;

  [self.cellAdapters removeAllObjects];
  [self.cellAdapters addObject:cellAdapter];
  [self.weakTableViews removeAllObjects];
  [self.weakTableViews addObject:[LcWeakReference weakReferenceWithObject:tableView]];
}

- (void)addCellAdapter:(LcCellAdapter*)cellAdapter forTableView:(UITableView*)tableView {
  LC_CHECK_NOT_NULL(cellAdapter);
  LC_CHECK_NOT_NULL(tableView);
  if (self.cellAdapters == nil) {
    self.cellAdapters = [NSMutableArray array];
  }
  if (self.weakTableViews == nil) {
    self.weakTableViews = [NSMutableArray array];
  }
  LC_CHECK_TRUE(self.cellAdapters.count == self.weakTableViews.count);
  tableView.dataSource = cellAdapter;
  tableView.delegate = self;
  cellAdapter.delegate = self;
  cellAdapter.tableView = tableView;
  [self.cellAdapters addObject:cellAdapter];
  [self.weakTableViews addObject:[LcWeakReference weakReferenceWithObject:tableView]];
}

- (void)closeEstimatedRowHeightforTableView:(UITableView*)tableView {
  // in iOS11, Self-Sizing will auto open
  tableView.estimatedRowHeight = 0;
  tableView.estimatedSectionHeaderHeight = 0;
  tableView.estimatedSectionFooterHeight = 0;
}

- (LcCellAdapter*)cellAdapterForTableView:(UITableView*)tableView {
  if (self.weakTableViews.count > 0) {
    int index = -1;
    for (LcWeakReference* weakTableView in self.weakTableViews) {
      ++index;
      if (weakTableView.object == tableView) {
        return self.cellAdapters[index];
      }
    }
    LC_FAIL();
  }
  return nil;
}

#pragma mark - UITableViewDelegate
- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath {
  LcCellAdapter* cellAdapter = [self cellAdapterForTableView:tableView];
  return [cellAdapter tableView:tableView heightForRowAtIndexPath:indexPath];
}

- (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
  [tableView deselectRowAtIndexPath:indexPath animated:YES];
  LcCellAdapter* cellAdapter = [self cellAdapterForTableView:tableView];
  [cellAdapter onRowSelectedAtIndex:indexPath.row];
}

- (BOOL)tableView:(UITableView*)tableView shouldHighlightRowAtIndexPath:(NSIndexPath*)indexPath {
  LcCellAdapter* cellAdapter = [self cellAdapterForTableView:tableView];
  return [[cellAdapter cellDataAtIndex:(int)indexPath.row] clickable];
}

- (void)scrollViewDidScroll:(UIScrollView*)scrollView {
  if (scrollView.isTracking) {
    [self dismissKeyboard];
    [self dismissMenuController];
  }
}

- (void)tableView:(UITableView*)tableView
      willDisplayCell:(UITableViewCell*)cell
    forRowAtIndexPath:(NSIndexPath*)indexPath {
  if ([tableView.tableFooterView isKindOfClass:LcLoadMoreView.class]) {
    LcCellAdapter* cellAdapter = [self cellAdapterForTableView:tableView];
    if (indexPath.row == cellAdapter.allCellDatas.count - 1) {
      LcLoadMoreView* loadMoreView = (LcLoadMoreView*)tableView.tableFooterView;
      [loadMoreView triggerShow];
    }
  }
  LcCellAdapter* cellAdapter = [self cellAdapterForTableView:tableView];
  [cellAdapter tableView:tableView willDisplayCell:cell forRowAtIndexPath:indexPath];
}

- (void)tableView:(UITableView*)tableView
    didEndDisplayingCell:(UITableViewCell*)cell
       forRowAtIndexPath:(NSIndexPath*)indexPath {
  LcCellAdapter* cellAdapter = [self cellAdapterForTableView:tableView];
  [cellAdapter tableView:tableView didEndDisplayingCell:cell forRowAtIndexPath:indexPath];
}

#pragma mark - LcNotificationDelegate
- (void)notificationReceived:(NSString*)notification auxiliary:(id)auxiliary {
  // do nothing
}

#pragma mark - LcCellAdapterDelegate
- (void)onLoadMore:(LcCellAdapter*)cellAdapter {
  LC_FAIL();
}

- (void)onSelectionChanged:(NSString*)group cellAdapter:(LcCellAdapter*)cellAdapter {
  // do nothing
}

- (void)onCommitEditing:(NSIndexPath*)indexPath cellAdapter:(LcCellAdapter*)cellAdapter {
  // do nothing
}

#pragma mark - KeyBoard
- (BOOL)disallowDismissKeyboard {
  return NO;
}

- (void)dismissKeyboard {
  if (!self.disallowDismissKeyboard) {
    [self.view endEditing:YES];
  }
}

// default return YES;
- (BOOL)allowDismissMenuController {
  return YES;
}

- (void)dismissMenuController {
  if (!self.allowDismissMenuController) {
    return;
  }
  UIMenuController* menuController = [UIMenuController sharedMenuController];
  if (menuController.isMenuVisible) {
    [menuController setMenuVisible:NO animated:YES];
  }
}

#pragma mark - UIInterfaceOrientation

- (BOOL)shouldAutorotate {
  if ([UIApplication sharedApplication].statusBarOrientation ==
          UIInterfaceOrientationLandscapeLeft ||
      [UIApplication sharedApplication].statusBarOrientation ==
          UIInterfaceOrientationLandscapeRight) {
    return YES;
  }
  return NO;
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
  return UIInterfaceOrientationMaskPortrait;
}

// 最优先显示的屏幕方向
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
  return UIInterfaceOrientationPortrait;
}

- (NSString*)hierarchyContext {
  return NSStringFromClass(self.class);
}

- (void)addListenApplicationState {
  if (!self.listeningAppState) {
    self.listeningAppState = YES;
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(applicationWillResignActive)
                                                 name:UIApplicationWillResignActiveNotification
                                               object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(applicationDidEnterBackground)
                                                 name:UIApplicationDidEnterBackgroundNotification
                                               object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(applicationWillEnterForeground)
                                                 name:UIApplicationWillEnterForegroundNotification
                                               object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(applicationDidBecomeActive)
                                                 name:UIApplicationDidBecomeActiveNotification
                                               object:nil];
  }
}

- (void)removeListenApplicationState {
  if (self.listeningAppState) {
    self.listeningAppState = NO;
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIApplicationWillResignActiveNotification
                                                  object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIApplicationDidEnterBackgroundNotification
                                                  object:nil];
    [[NSNotificationCenter defaultCenter]
        removeObserver:self
                  name:UIApplicationWillEnterForegroundNotification
                object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIApplicationDidBecomeActiveNotification
                                                  object:nil];
  }
}

- (void)applicationWillResignActive {
}

- (void)applicationDidEnterBackground {
}

- (void)applicationWillEnterForeground {
}

- (void)applicationDidBecomeActive {
}

@end
